package instructions;

import expressions.BadExpressionException;
import expressions.Expression;
import values.Boolean;
import values.Value;
import base.AST;
import base.Environment;
import base.Interpreter;

public class If implements Instruction {

	private AST test;
	private Instruction pass;
	private Instruction fail;
	
	/**
	 *  Creates the block
	 *  if (test) {
	 *  	pass
	 *  } else {
	 *  	fail
	 *  }
	 */
	public If(AST test, Instruction pass, Instruction fail) {
		assert test instanceof Expression || test instanceof Value;
		this.test = test;
		this.pass = pass;
		this.fail = fail;
	}
	
	/**
	 * if test corresponds to the Boolean true, executes pass, else executes fail
	 */
	public Environment instr(Environment env) throws BadInstructionException {
		Environment newEnv = env.clone();
		
		try {
		
		Boolean testBoolean = Interpreter.getBoolean(this.test, env);
		
		if (testBoolean != null && testBoolean.eval()) {
			newEnv = this.pass.instr(newEnv);
		} else if (this.fail != null) {
			newEnv = this.fail.instr(newEnv);
		}
			
		return newEnv;
		
		} catch (BadExpressionException e) {
			throw new BadInstructionException(e,
					"Evaluation of the if statement condition does not give a boolean value");
		}
	}
	
}
